package com.chuanyun.wechatcheckin.service;

import com.chuanyun.wechatcheckin.config.WechatConfig;
import com.chuanyun.wechatcheckin.model.wechat.CheckinDataRequest;
import com.chuanyun.wechatcheckin.model.wechat.CheckinDataResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;

/**
 * 打卡记录服务类
 * 专门处理企业微信打卡记录相关的业务逻辑
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CheckinRecordService {

    private final WechatConfig wechatConfig;
    private final WechatApiService wechatApiService;
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 获取打卡记录数据
     * @param openCheckinDataType 打卡类型（1：上下班打卡；2：外出打卡；3：全部打卡）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param userIdList 用户ID列表（不超过100个）
     * @return 打卡记录响应
     * @throws Exception 异常
     */
    public CheckinDataResponse getCheckinData(Integer openCheckinDataType, LocalDateTime startTime, 
                                            LocalDateTime endTime, List<String> userIdList) throws Exception {
        
        // 参数验证
        if (userIdList == null || userIdList.isEmpty()) {
            throw new IllegalArgumentException("用户ID列表不能为空");
        }
        
        if (userIdList.size() > 100) {
            throw new IllegalArgumentException("用户列表不能超过100个，当前数量: " + userIdList.size());
        }
        
        // 时间跨度验证（不超过30天）
        long daysBetween = java.time.Duration.between(startTime, endTime).toDays();
        if (daysBetween > 30) {
            throw new IllegalArgumentException("时间跨度不能超过30天，当前跨度: " + daysBetween + "天");
        }
        
        String accessToken = wechatApiService.getCheckinAccessToken();
        
        // 构建请求参数
        CheckinDataRequest request = new CheckinDataRequest(
            openCheckinDataType,
            startTime.toEpochSecond(ZoneOffset.of("+8")), // 转换为Unix时间戳（北京时间）
            endTime.toEpochSecond(ZoneOffset.of("+8")),
            userIdList
        );
        
        // 构建请求URL
        String url = wechatConfig.getApi().getBaseUrl() + "/cgi-bin/checkin/getcheckindata?access_token=" + accessToken;
        
        log.info("开始获取打卡记录 - 类型: {}, 时间范围: {} 到 {}, 用户数量: {}", 
            openCheckinDataType, startTime, endTime, userIdList.size());
        
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(url);
            
            // 设置请求体
            String requestBody = objectMapper.writeValueAsString(request);
            httpPost.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON));
            
            log.debug("打卡记录请求参数: {}", requestBody);
            
            return httpClient.execute(httpPost, response -> {
                String responseBody = EntityUtils.toString(response.getEntity());
                log.debug("打卡记录API响应: {}", responseBody);
                
                CheckinDataResponse checkinResponse = objectMapper.readValue(responseBody, CheckinDataResponse.class);
                
                if (checkinResponse.isSuccess()) {
                    int recordCount = checkinResponse.getCheckinData() != null ? checkinResponse.getCheckinData().size() : 0;
                    log.info("成功获取打卡记录，共 {} 条记录", recordCount);
                    return checkinResponse;
                } else {
                    log.error("获取打卡记录失败: {} - {}", checkinResponse.getErrCode(), checkinResponse.getErrMsg());
                    throw new RuntimeException("获取打卡记录失败: " + checkinResponse.getErrMsg());
                }
            });
        }
    }
    
    /**
     * 批量获取打卡记录数据（自动分批处理）
     * @param openCheckinDataType 打卡类型
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param allUserIds 所有用户ID列表
     * @return 所有打卡记录
     * @throws Exception 异常
     */
    public List<CheckinDataResponse.CheckinRecord> getCheckinDataBatch(Integer openCheckinDataType, 
                                                                      LocalDateTime startTime, 
                                                                      LocalDateTime endTime, 
                                                                      List<String> allUserIds) throws Exception {
        
        if (allUserIds == null || allUserIds.isEmpty()) {
            log.warn("用户ID列表为空，返回空结果");
            return new ArrayList<>();
        }
        
        List<CheckinDataResponse.CheckinRecord> allRecords = new ArrayList<>();
        int batchSize = 100; // 每批最多100个用户
        int totalBatches = (int) Math.ceil((double) allUserIds.size() / batchSize);
        
        log.info("开始批量获取打卡记录 - 总用户数: {}, 分批数: {}, 每批大小: {}", 
            allUserIds.size(), totalBatches, batchSize);
        
        for (int i = 0; i < totalBatches; i++) {
            int startIndex = i * batchSize;
            int endIndex = Math.min(startIndex + batchSize, allUserIds.size());
            List<String> batchUserIds = allUserIds.subList(startIndex, endIndex);
            
            log.info("处理第 {}/{} 批，用户数量: {}", i + 1, totalBatches, batchUserIds.size());
            
            try {
                CheckinDataResponse response = getCheckinData(openCheckinDataType, startTime, endTime, batchUserIds);
                
                if (response.getCheckinData() != null) {
                    allRecords.addAll(response.getCheckinData());
                    log.info("第 {}/{} 批完成，获取到 {} 条记录", i + 1, totalBatches, response.getCheckinData().size());
                }
                
                // 避免频率限制，批次间稍作延迟
                if (i < totalBatches - 1) {
                    Thread.sleep(100); // 延迟100毫秒
                }
                
            } catch (Exception e) {
                log.error("第 {}/{} 批处理失败: {}", i + 1, totalBatches, e.getMessage(), e);
                // 继续处理下一批，不中断整个流程
            }
        }
        
        log.info("批量获取打卡记录完成 - 总记录数: {}", allRecords.size());
        return allRecords;
    }

    /**
     * 获取指定用户在指定时间范围内的所有打卡记录
     * @param userId 用户ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 打卡记录列表
     * @throws Exception 异常
     */
    public List<CheckinDataResponse.CheckinRecord> getUserCheckinRecords(String userId, 
                                                                        LocalDateTime startTime, 
                                                                        LocalDateTime endTime) throws Exception {
        List<String> userIds = List.of(userId);
        CheckinDataResponse response = getCheckinData(3, startTime, endTime, userIds); // 获取全部打卡类型
        return response.getCheckinData() != null ? response.getCheckinData() : new ArrayList<>();
    }

    /**
     * 获取所有用户在指定时间范围内的打卡记录
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 所有打卡记录
     * @throws Exception 异常
     */
    public List<CheckinDataResponse.CheckinRecord> getAllUsersCheckinRecords(LocalDateTime startTime, 
                                                                            LocalDateTime endTime) throws Exception {
        List<String> allUserIds = wechatApiService.getAllUserIds();
        return getCheckinDataBatch(3, startTime, endTime, allUserIds); // 获取全部打卡类型
    }

    /**
     * 获取今天的打卡记录（从今天0点到当前时间）
     * @return 今天的所有打卡记录
     * @throws Exception 异常
     */
    public List<CheckinDataResponse.CheckinRecord> getTodayCheckinRecords() throws Exception {
        LocalDateTime startTime = LocalDateTime.now().toLocalDate().atStartOfDay(); // 今天0点
        LocalDateTime endTime = LocalDateTime.now(); // 当前时间
        
        log.info("获取今天的打卡记录 - 时间范围: {} 到 {}", startTime, endTime);
        
        List<String> allUserIds = wechatApiService.getAllUserIds();
        return getCheckinDataBatch(3, startTime, endTime, allUserIds); // 获取全部打卡类型
    }
}